﻿using ArcGIS.Desktop.Core.Geoprocessing;
using Baci.Net.ToolKit.ArcGISProGeoprocessor.Models;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Baci.ArcGIS
{
    public static class Geoprocessor
    {
        public static string GPMessageboxTitle = "GpMessages";
        public static async Task<bool> ExcuteAsync(string tooName, IReadOnlyList<string> parameters,
            IEnumerable<KeyValuePair<string, string>> environments = null,
            CancellationTokenSource cancellationTokenSource = null, bool showResultDig = false,
            GPToolExecuteEventHandler gPToolExecuteEventHandler = null,
            GPExecuteToolFlags gPExecuteToolFlags = GPExecuteToolFlags.Default)
        {
            IGPMessage[] gPMsgs = null;
            IGPResult GPResult = await ExcuteAsync(tooName, parameters, cancellationTokenSource, environments, gPToolExecuteEventHandler, gPExecuteToolFlags);

            gPMsgs = GPResult.Messages.ToArray();

            if (GPResult.IsFailed != true && !(GPResult.Messages.Count() == 0))
            {
                //成功时输出
                if (showResultDig)
                    Geoprocessing.ShowMessageBox(GPResult.Messages, GPMessageboxTitle, GPResult.HasWarnings ? GPMessageBoxStyle.Warning : GPMessageBoxStyle.Default);
                return true;
            }
            else
            {
                //失败时输出
                if (!(GPResult.ErrorMessages.Count() == 0))
                {
                    if (showResultDig)
                        Geoprocessing.ShowMessageBox(GPResult.ErrorMessages, GPMessageboxTitle, GPMessageBoxStyle.Error);
                }
                else//意外：参数问题输出
                {
                    if (gPMsgs.Count() <= 0)
                        throw new Exception();//参数输入错误：1. 地址、名称错误或不存在 2. 参数类型错误、参数数量错误
                    if (showResultDig)
                    {
                        Geoprocessing.ShowMessageBox(gPMsgs, GPMessageboxTitle, GPMessageBoxStyle.Warning);
                    }
                }
                return false;
            }
        }

        public static async Task<IGPResult> ExcuteAsync(string tooName, IReadOnlyList<string> parameters, CancellationTokenSource cancellationTokenSource,
            IEnumerable<KeyValuePair<string, string>> environments, GPToolExecuteEventHandler gPToolExecuteEventHandler, GPExecuteToolFlags gPExecuteToolFlags = GPExecuteToolFlags.Default)
        {
            return await Geoprocessing.ExecuteToolAsync(tooName, parameters, environments, cancellationTokenSource?.Token,
              gPToolExecuteEventHandler, gPExecuteToolFlags);
        }

        public static void Show(string toolPath, IEnumerable<string> values, IEnumerable<KeyValuePair<string, string>> environments = null, bool newSubPane = false, GPToolExecuteEventHandler callback = null)
        {
            Geoprocessing.OpenToolDialog(toolPath, values, environments, newSubPane, callback);
        }

        public static Task<IGPResult> ShowAsync(string toolPath, IEnumerable<string> values = null, IEnumerable<KeyValuePair<string, string>> environments = null,
            GPToolExecuteEventHandler callback = null, GPExecuteToolFlags executeFlags = GPExecuteToolFlags.Default, GPToolDialogFlags dialogFlags = GPToolDialogFlags.Default, string dialogTitle = null)
        {
            return Geoprocessing.OpenToolDialogAsync(toolPath, values, environments, callback, executeFlags, dialogFlags);
        }


    }

    public static partial class Extension
    {
        public static async Task<bool> Run(this IGPProcess gPProcess, CancellationTokenSource cancellationTokenSource = null, bool showResultDig = false,
            IEnumerable<KeyValuePair<string, string>> environments = null, GPToolExecuteEventHandler gPToolExecuteEventHandler = null,
            GPExecuteToolFlags gPExecuteToolFlags = GPExecuteToolFlags.None)
        {
            var parameterInfo = Geoprocessing.MakeValueArray(gPProcess.ParameterInfo);

            if (environments == null)
                environments = gPProcess.Environments;

            return await Geoprocessor.ExcuteAsync(gPProcess.CallName, parameterInfo, environments, cancellationTokenSource,
                showResultDig, gPToolExecuteEventHandler, gPExecuteToolFlags);
        }

        public static void Show(this IGPProcess gPProcess, IEnumerable<KeyValuePair<string, string>> environments = null, bool newSubPane = false,
            GPToolExecuteEventHandler callback = null)
        {
            var parameterInfo = Geoprocessing.MakeValueArray(gPProcess.ParameterInfo);

            if (environments == null)
                environments = gPProcess.Environments;

            Geoprocessor.Show(gPProcess.CallName, parameterInfo, environments, newSubPane, callback);
        }

        /// <summary>
        /// 可以获取手动执行GP工具的执行结果
        /// </summary>
        /// <param name="gPProcess"></param>
        /// <param name="values"></param>
        /// <param name="environments"></param>
        /// <param name="callback"></param>
        /// <param name="executeFlags"></param>
        /// <param name="dialogFlags"></param>
        /// <param name="dialogTitle"></param>
        /// <returns></returns>
        public static Task<IGPResult> ShowAsync(this IGPProcess gPProcess, IEnumerable<string> values = null, IEnumerable<KeyValuePair<string, string>> environments = null,
            GPToolExecuteEventHandler callback = null, GPExecuteToolFlags executeFlags = GPExecuteToolFlags.Default, GPToolDialogFlags dialogFlags = GPToolDialogFlags.Default, string dialogTitle = null)
        {
            var parameterInfo = Geoprocessing.MakeValueArray(gPProcess.ParameterInfo);

            if (environments == null)
                environments = gPProcess.Environments;

            return Geoprocessor.ShowAsync(gPProcess.CallName, parameterInfo, environments, callback, executeFlags, dialogFlags, dialogTitle);
        }

    }
}
